package com.fhj.utils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import android.os.Environment;

import android.util.LruCache;

import com.android.volley.*;
import com.android.volley.toolbox.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.security.MessageDigest;
import java.util.HashMap;

public class CacheUtils {
	/**
	 * 图片加载器
	 */
	private ImageLoader loader;
	/**
	 * 实现带有SD卡文件缓存的 ImageCache 实例。
	 */
	private MyImageCache imageCache;
	private RequestQueue requestQueue;
	private String path;
	private NetworkImageView imageView;
	public CacheUtils(){
		
	}
	public CacheUtils(Context context, NetworkImageView imageView,RequestQueue requestQueue,String path) {
		// 开启一个请求队列，接受各种请求
		this.requestQueue=requestQueue;

		// 图片缓存，这个仔细看
		imageCache = new MyImageCache(context);

		// 利用请求队列创建图片加载器, 使用 MyImageCache 作为缓存管理
		loader = new ImageLoader(requestQueue, imageCache);

		this.imageView = imageView;

		this.path=path;
		
		imageView.setImageUrl(path, loader);
		
	}
	

	public void ClearCache() {
		Cache cache = requestQueue.getCache();
		// 创建 ClearCacheRequest 请求，这个请求可以设置清除哪个缓冲区
		ClearCacheRequest request = new ClearCacheRequest(cache, null);
		requestQueue.add(request);
	}

	/**
	 * 图片缓存
	 */
	public static class MyImageCache implements ImageLoader.ImageCache {
		/**
		 * LRU 缓存区
		 */
		private LruCache<String, Bitmap> lruCache;

		/**
		 * 软引用缓存
		 */
		private HashMap<String, SoftReference<Bitmap>> softCache;

		/**
		 * Context 用于获取当前应用程序的 存储卡缓存文件目录，这个必须设置
		 */
		private Context context;

		/**
		 * 创建图片缓冲区实例
		 * 
		 * @param ct
		 *            Context 这个字段必须设置，因为需要通过这个变量来获取缓冲区目录
		 */
		public MyImageCache(Context ct) {
			// 4MB 内存大小
			lruCache = new LruCache<String, Bitmap>(4 * 1024 * 1024);
			// 软引用缓存
			softCache = new HashMap<String, SoftReference<Bitmap>>();
			context = ct;
		}

		/**
		 * 从缓存加载，如果返回null, 那么就会自动从网络加载
		 * 
		 * @param url
		 * @return
		 */
		@Override
		public Bitmap getBitmap(String url) {
			Bitmap ret = null;
			if (url != null) {

				// 第一步，从LRU缓存获取图片
				Bitmap bitmap = lruCache.get(url);

				if (bitmap != null) { // 从 LRU Cache 中找到了数据
					ret = bitmap; // 找到图片直接返回
				} else {
					// 没有从 LRU Cache 中找到，就要检查软引用的数据是否有

					SoftReference<Bitmap> reference = softCache.get(url);
					if (reference != null) {
						bitmap = reference.get();
					}

					if (bitmap != null) { // 从软引用中 找到实际的数据，则返回
						ret = bitmap;
						lruCache.put(url, ret); // 更新LRU缓存
					} else {
						// LruCache 和 SoftReference 中都没有，那么就要检查SD卡中是否存在？

						// TODO 从 SD卡查找

						String state = Environment.getExternalStorageState();
						if (state.equals(Environment.MEDIA_MOUNTED)) {
							// 存在SD卡，进行读取

							// File directory =
							// Environment.getExternalStorageDirectory();

							// File imageCacheFolder = new File(directory,
							// "VolleyTestImages");

							// 所有在此目录中存储的文件，在应用程序卸载的时候，被Android系统清空
							// 只有自身程序可以访问，此目录，其他程序无法访问
							File cacheDir = context.getExternalCacheDir();

							File imageCacheFolder = new File(cacheDir, "images");

							boolean bok = true;

							if (!imageCacheFolder.exists()) {
								bok = imageCacheFolder.mkdirs();
							}

							if (bok) {
								try {
									MessageDigest digest = MessageDigest
											.getInstance("MD5");
									digest.update(url.getBytes());
									byte[] bytes = digest.digest();
									String hex = hex(bytes);

									File targetFile = new File(
											imageCacheFolder, hex);

									if (targetFile.exists()) {
										// TODO 读取文件，并且生成 Bitmap 返回，并且，加入到
										// LruCache, 并且 加入到 SoftReference
										try {
											FileInputStream fin = new FileInputStream(
													targetFile);
											bitmap = BitmapFactory
													.decodeStream(fin);
											fin.close();
											ret = bitmap;

											lruCache.put(url, bitmap);
											softCache.put(url,
													new SoftReference<Bitmap>(
															bitmap));

										} catch (IOException ioe) {

										}
									}
								} catch (Exception ex) {
									ex.printStackTrace();
								}
							}
						}

					}

				}
			}
			return ret;
		}

		/**
		 * @param url
		 * @param bitmap
		 */
		@Override
		public void putBitmap(String url, Bitmap bitmap) {
			lruCache.put(url, bitmap);
			softCache.put(url, new SoftReference<Bitmap>(bitmap));

			// TODO 把bitmap 存储到 SD卡文件中

			// 所有在此目录中存储的文件，在应用程序卸载的时候，被Android系统清空
			// 只有自身程序可以访问，此目录，其他程序无法访问
			File cacheDir = context.getExternalCacheDir();

			File imageCacheFolder = new File(cacheDir, "images");

			boolean bok = true;

			if (!imageCacheFolder.exists()) {
				bok = imageCacheFolder.mkdirs();
			}

			if (bok) {
				try {
					MessageDigest digest = MessageDigest.getInstance("MD5");
					digest.update(url.getBytes());
					byte[] bytes = digest.digest();
					String hex = hex(bytes);

					File targetFile = new File(imageCacheFolder, hex);

					try {
						if (!targetFile.exists()) {
							bok = targetFile.createNewFile();
						}
					} catch (IOException ioe) {
						ioe.printStackTrace();
					}

					if (bok) {
						// TODO 写入文件
						try {

							FileOutputStream fout = new FileOutputStream(
									targetFile);

							bitmap.compress(Bitmap.CompressFormat.PNG, 100,
									fout);

							fout.close();
						} catch (IOException ioe) {

						}
					}
				} catch (Exception ex) {
					ex.printStackTrace();
				}
			}

		}
	}

	private static String hex(byte[] bytes) {
		String ret = null;
		if (bytes != null) {
			StringBuilder sb = new StringBuilder();
			for (byte aByte : bytes) {
				int h = (aByte >> 4) & 0x0F;
				int l = (aByte & 0x0F);
				char ch = 0, cl = 0;
				if (h > 9) {
					ch = (char) ('A' + h - 10);
				} else {
					ch = (char) (h + '0');
				}
				if (l > 9) {
					cl = (char) ('A' + l - 10);
				} else {
					cl = (char) (l + '0');
				}

				sb.append(ch).append(cl);
			}
			ret = sb.toString();
			sb = null;
		}
		return ret;
	}

}
